import os
import re
import subprocess
import tempfile
from tracemalloc import start
import uuid
from typing import Dict, List, Any, Optional, Tuple, Literal
from dataclasses import dataclass
from PIL import Image, ImageDraw, ImageFont
from numpy import angle
from src.database.dao import upload_file_dao
from src.database.dao_factory import DAOFactory
from src.utils.logger import log_info, log_error, log_warning


@dataclass
class FootballMatchInfo:
    """足球比赛信息，从字幕中提取"""
    start_time: float  # 字幕开始时间（秒）
    end_time: float    # 字幕结束时间（秒）
    match_image: Optional[str] = None  # 比赛图片路径
    team1_image: Optional[str] = None  # 队伍1图片路径
    team2_image: Optional[str] = None  # 队伍2图片路径
    score1: Optional[int] = None       # 队伍1比分
    score2: Optional[int] = None       # 队伍2比分
    original_text: str = ""            # 原始字幕文本

@dataclass
class CustomInfo:
    """自定义图标信息"""
    start_time: float  # 字幕开始时间（秒）
    end_time: float    # 字幕结束时间（秒）
    type: str = 'VIDEO'  # 文件类型
    angle: float = 0.0  # 旋转角度
    x: float = 0.0  # X坐标
    y: float = 0.0  # Y坐标
    h: float = 0.0  # 高度
    w: float = 0.0  # 宽度
    file_path: str = ""  # 文件路径
    original_text: str = ""

class FootballIconVideoGenerator:
    """足球图标视频生成器，将图标叠加到视频上"""
    
    def __init__(self, icons_base_dir: str):
        """
        初始化足球图标视频生成器
        
        Args:
            icons_base_dir: 图标文件的基础目录
        """
        self.icons_base_dir = icons_base_dir
        self.dao_factory = DAOFactory.get_instance()
        
        # 确保目录存在
        os.makedirs(os.path.join(self.icons_base_dir, "match"), exist_ok=True)
        os.makedirs(os.path.join(self.icons_base_dir, "team"), exist_ok=True)
        
        # 用于隐藏命令行窗口
        self.startupinfo = None
        if os.name == 'nt':
            self.startupinfo = subprocess.STARTUPINFO()
            self.startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

    def _parse_text_with_custom(self, text, start_time, end_time) -> List[CustomInfo]:
        """
        解析SRT文件，提取自定义图标信息
        格式: [football_icon:custom:318:1.262_563.311_1413.844_287.649_383.532:overlay]
        参数顺序: file_id:angle_x_y_h_w:file_name
        """
        # 修正的正则表达式: [football_icon:custom:file_id:angle_x_y_h_w:overlay]
        icon_pattern = r'\[football_icon:custom:(\d+):([^:]+):(\w+)\]'
        matchs = re.findall(icon_pattern, text)
        results = []
        if not matchs:
            return results
            
        for  file_id, coords_str, file_name  in matchs:
            # 创建CustomInfo实例，提供所有必需参数
            custom_info = CustomInfo(
                start_time=start_time, 
                end_time=end_time, 
                original_text=text
            )
            
            # 解析坐标字符串 (格式: angle_x_y_h_w)
            coords = coords_str.split('_')
            if len(coords) >= 5:
                custom_info.angle = float(coords[0]) if coords[0] else 0.0
                custom_info.x = float(coords[1]) if coords[1] else 0.0
                custom_info.y = float(coords[2]) if coords[2] else 0.0
                custom_info.h = float(coords[3]) if coords[3] else 0.0
                custom_info.w = float(coords[4]) if coords[4] else 0.0
            
            # 获取文件路径
            upload_file_dao = self.dao_factory.get_uploaded_file_dao()
            uploaded_file = upload_file_dao.get_by_id(int(file_id))

            if uploaded_file:
                custom_info.type = uploaded_file.file_type
                custom_info.file_path = uploaded_file.file_path
                results.append(custom_info)
        return results
    
    def _parse_text_with_team_or_match(self, text, start_time, end_time) -> Optional[FootballMatchInfo]:
        """
        解析SRT文件，提取足球比赛信息
        格式：[football_icon:team:afc-wimbledon.png:3][football_icon:team:arsenal-women.png:8][football_icon:match:LaLiga.png]
        """
        match_info = FootballMatchInfo(start_time=start_time, end_time=end_time, original_text=text)
        icon_pattern = r'\[football_icon:([^:]+):(\d+):([^:\]]+)(?::(\d+))?\]'
        icons = re.findall(icon_pattern, text)
        
        # 用于跟踪团队图标数量
        team_count = 0
        uploaded_file_dao = self.dao_factory.get_uploaded_file_dao()
        for icon_type,file_id, filename, score in icons:
            if icon_type not in ['match', 'team']:
                log_warning(f"未知图标类型: {icon_type}，跳过处理")
                continue
            if icon_type == 'match':
                match_info.match_image = uploaded_file_dao.get_by_id(file_id).file_path
            elif icon_type == 'team':
                # 第一个team是team1，第二个是team2
                if team_count == 0:
                    match_info.team1_image = uploaded_file_dao.get_by_id(file_id).file_path
                    match_info.team1_name = filename  # 保存队伍名称
                    if score:  # 如果分数存在
                        match_info.score1 = int(score)
                    team_count += 1
                elif team_count == 1:
                    match_info.team2_image = uploaded_file_dao.get_by_id(file_id).file_path
                    match_info.team2_name = filename  # 保存队伍名称
                    if score:  # 如果分数存在
                        match_info.score2 = int(score)
                    team_count += 1
        # 只有当至少有一个比赛元素被提取出来时才添加
        if match_info.match_image or match_info.team1_image or match_info.team2_image:
            return match_info

    def _parse_srt_file(self, srt_path: str) -> List[FootballMatchInfo|CustomInfo]:
        """
        解析SRT文件，提取足球比赛信息
        Args:
            srt_path: SRT字幕文件路径
            
        Returns:
            包含足球比赛信息的列表
        """
        if not os.path.exists(srt_path):
            raise FileNotFoundError(f"SRT文件不存在: {srt_path}")
        
        result = []
        
        with open(srt_path, 'r', encoding='utf-8') as file:
            content = file.read()
        
        # 分割为字幕条目
        # SRT格式: 序号\n时间码\n字幕内容\n空行
        subtitle_blocks = re.split(r'\n\s*\n', content.strip())
        
        for block in subtitle_blocks:
            lines = block.strip().split('\n')
            if len(lines) < 3:
                continue  # 跳过格式不正确的字幕块

            # 解析时间码
            time_line = lines[1]
            time_match = re.search(r'(\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2},\d{3})', time_line)
            if not time_match:
                continue
                
            start_time = self._convert_srt_time_to_seconds(time_match.group(1))
            end_time = self._convert_srt_time_to_seconds(time_match.group(2))
            
            # 获取字幕文本内容
            text = '\n'.join(lines[2:])
            # 提取新格式标记
            # 新格式: [football_icon:type:file_id:filename:score]，其中file_id为数字
            if ("[football_icon:team" in text or "[football_icon:match" in text):
                # 提取所有足球图标标记
                match_info = self._parse_text_with_team_or_match(text, start_time, end_time) 
                if match_info:
                    result.append(match_info)
            if "[football_icon:custom" in text:
                custom_info = self._parse_text_with_custom(text, start_time, end_time)
                result.extend(custom_info)
        return result
    
    def _convert_srt_time_to_seconds(self, time_str: str) -> float:
        """将SRT时间格式转换为秒数"""
        hours, minutes, seconds = time_str.split(':')
        seconds, milliseconds = seconds.split(',')
        return (int(hours) * 3600 + 
                int(minutes) * 60 + 
                int(seconds) + 
                int(milliseconds) / 1000)
    
    def _get_video_info(self, video_path: str) -> Dict[str, Any]:
        """获取视频基本信息"""
        try:
            # 获取视频分辨率
            cmd = [
                "ffprobe", 
                "-v", "error", 
                "-select_streams", "v:0", 
                "-show_entries", "stream=width,height", 
                "-of", "csv=p=0", 
                video_path
            ]
            
            output = subprocess.check_output(cmd, startupinfo=self.startupinfo).decode().strip()
            width, height = map(int, output.split(','))
            
            # 获取视频时长
            cmd = [
                "ffprobe", 
                "-v", "error", 
                "-show_entries", "format=duration", 
                "-of", "csv=p=0", 
                video_path
            ]
            
            duration = float(subprocess.check_output(cmd, startupinfo=self.startupinfo).decode().strip())
            
            return {
                "success": True,
                "width": width,
                "height": height,
                "duration": duration
            }
        except Exception as e:
            log_error(f"获取视频信息失败: {e}")
            return {"success": False, "message": str(e)}
    
    def _create_score_image(self, score1: Optional[int] = None, score2: Optional[int] = None, width: int = 400, height: int = 120) -> str:
        """
        创建比分图像 - 使用白色加粗字体，无背景，无描边
        
        Args:
            score1: 队伍1比分，如果为None则显示X
            score2: 队伍2比分，如果为None则显示X
            width: 图像宽度
            height: 图像高度
            
        Returns:
            临时比分图像的文件路径
        """
        # 创建透明背景的图像
        image = Image.new('RGBA', (width, height), (0, 0, 0, 0))
        draw = ImageDraw.Draw(image)
        
        font = ImageFont.truetype("arialbd.ttf", 60)  # 更大的字体

    
        # 确定显示文本 - 如果两个分数都是None或默认为X，则显示VS
        score_text = ""
        score1_text = "X" if score1 is None else str(score1)
        score2_text = "X" if score2 is None else str(score2)
        
        if score1_text == "X" and score2_text == "X":
            score_text = "VS"
        else:
            score_text = f"{score1_text} : {score2_text}"
        
        # 计算文本宽度
        text_width = draw.textlength(score_text, font=font) if hasattr(draw, 'textlength') else font.getlength(score_text)
        text_x = (width - text_width) // 2
        text_y = (height - 60) // 2  # 基于字体大小调整垂直位置
        
        # 直接绘制白色文本，不加描边
        draw.text((text_x, text_y), score_text, font=font, fill=(255, 255, 255, 255))  # 改为白色
    
        # 保存到临时文件
        temp_file = os.path.join(tempfile.gettempdir(), f"score_{uuid.uuid4()}.png")
        image.save(temp_file, "PNG")
        
        return temp_file
    
    def _create_team_name_image(self, team_name: str, width: int = 300, height: int = 60) -> str:
        """
        创建队伍名称图像 - 使用白色字体，无背景
        
        Args:
            team_name: 队伍名称
            width: 图像宽度
            height: 图像高度
            
        Returns:
            临时队伍名称图像的文件路径
        """
        # 创建透明背景的图像
        image = Image.new('RGBA', (width, height), (0, 0, 0, 0))
        draw = ImageDraw.Draw(image)
        
        # 尝试加载字体，如果失败则使用默认字体
        font = ImageFont.truetype("arialbd.ttf", 30)  # 30px字体
    
        # 计算文本宽度
        text_width = draw.textlength(team_name, font=font) if hasattr(draw, 'textlength') else font.getlength(team_name)
        text_x = (width - text_width) // 2
        text_y = (height - 30) // 2  # 基于字体大小调整垂直位置
        
        # 直接绘制白色文本
        draw.text((text_x, text_y), team_name, font=font, fill=(255, 255, 255, 255))
        
        # 保存到临时文件
        temp_file = os.path.join(tempfile.gettempdir(), f"teamname_{uuid.uuid4()}.png")
        image.save(temp_file, "PNG")
        
        return temp_file
    
    def _process_custom_icon(self, custom_info: CustomInfo, last_video: str, vindex: int, i: int, 
                           input_files: List[str], filter_complex: List[str], temp_files: List[str]) -> Optional[Tuple[str, int]]:
        """
        处理自定义图标信息
        
        Args:
            custom_info: 自定义图标信息
            last_video: 上一个视频流标识
            vindex: 当前输入文件索引
            i: 当前信息在列表中的索引
            input_files: 输入文件列表
            filter_complex: 过滤器复杂表达式列表
            temp_files: 临时文件列表
            
        Returns:
            (新的last_video, 新的vindex) 或 None
        """
        # 检查自定义文件是否存在
        if not custom_info.file_path or not os.path.exists(custom_info.file_path):
            log_warning(f"自定义图标文件不存在: {custom_info.file_path}")
            return None
        
        # 添加到输入文件列表
        input_files.append(custom_info.file_path)
        
        # 检测文件类型
        file_ext = os.path.splitext(custom_info.file_path)[1].lower()
        is_video = file_ext in ['.mp4', '.avi', '.mov', '.mkv', '.webm', '.flv']
        is_gif = file_ext == '.gif'
        
        # 获取子视频的时长（仅对视频文件）
        video_duration = None
        if is_video:
            try:
                video_info = self._get_video_info(custom_info.file_path)
                if video_info["success"]:
                    video_duration = video_info["duration"]
                    log_info(f"子视频时长: {video_duration}秒")
            except Exception as e:
                log_warning(f"获取子视频时长失败: {e}")
        elif is_gif:
            # 对于GIF文件，获取时长信息
            try:
                video_info = self._get_video_info(custom_info.file_path)
                if video_info["success"]:
                    video_duration = video_info["duration"]
                    log_info(f"GIF时长: {video_duration}秒（将循环播放）")
            except Exception as e:
                log_warning(f"获取GIF时长失败: {e}")
        
        # 计算实际的结束时间
        if video_duration and (is_video or is_gif):
            # 对于视频文件，使用开始时间 + 视频时长作为结束时间
            # 对于GIF文件，也使用其播放时长，但会通过loop滤镜循环播放
            actual_end_time = custom_info.start_time + video_duration
            if is_gif:
                # GIF需要循环播放直到SRT指定的结束时间
                actual_end_time = custom_info.end_time
                log_info(f"GIF将在 {custom_info.start_time}秒开始，{actual_end_time}秒结束（循环播放）")
            else:
                log_info(f"子视频将在 {custom_info.start_time}秒开始，{actual_end_time}秒自动结束（播放完成）")
        else:
            # 对于图片文件，使用原来的结束时间
            actual_end_time = custom_info.end_time
            log_info(f"图片将在 {custom_info.start_time}秒开始，{actual_end_time}秒结束")
        
        # 构建过滤器表达式
        filter_parts = []
        
        # 对于GIF文件，需要特殊处理以支持循环播放
        if is_gif:
            # GIF循环播放：使用loop滤镜让GIF在指定时间范围内循环
            # 计算需要循环的次数
            display_duration = actual_end_time - custom_info.start_time
            if video_duration and video_duration > 0:
                loop_count = max(1, int(display_duration / video_duration) + 1)
            else:
                loop_count = -1  # 无限循环
            
            # 使用loop滤镜循环播放，然后用setpts控制时间
            filter_parts.append(f"[{vindex}:v]loop=loop={loop_count}:size=32767[looped{vindex}]")
            filter_parts.append(f"[looped{vindex}]setpts=PTS-STARTPTS+{custom_info.start_time}/TB[timed{vindex}]")
            current_stream = f"[timed{vindex}]"
            log_info(f"GIF循环设置: 循环{loop_count}次，显示时长{display_duration}秒")
        else:
            # 对于视频和图片文件，使用setpts来控制开始时间
            start_time_offset = custom_info.start_time
            filter_parts.append(f"[{vindex}:v]setpts=PTS-STARTPTS+{start_time_offset}/TB[timed{vindex}]")
            current_stream = f"[timed{vindex}]"
        
        # 处理缩放 - 如果指定了宽高则使用，否则按比例缩放
        if custom_info.w > 0 and custom_info.h > 0:
            scale_filter = f"scale={int(custom_info.w)}:{int(custom_info.h)}"
        elif custom_info.w > 0:
            scale_filter = f"scale={int(custom_info.w)}:-1"
        elif custom_info.h > 0:
            scale_filter = f"scale=-1:{int(custom_info.h)}"
        else:
            # 默认缩放到视频宽度的1/4
            scale_filter = "scale=iw/4:ih/4"
        
        filter_parts.append(f"{current_stream}{scale_filter}[scaled{vindex}]")
        current_stream = f"[scaled{vindex}]"
        
        # 处理旋转 - 如果有角度则添加旋转
        if custom_info.angle != 0.0:
            # 将角度转换为弧度 (FFmpeg使用弧度)
            angle_rad = custom_info.angle
            # 为了保持矩形，我们需要计算旋转后的合适尺寸
            # 使用旋转滤镜，设置输出宽高为足够大以包含整个旋转后的图像
            # ow和oh设置为输入宽高的对角线长度，确保旋转后不会被裁剪
            filter_parts.append(f"{current_stream}rotate={angle_rad}:fillcolor=0x00000000@0:ow='sqrt(iw*iw+ih*ih)':oh='sqrt(iw*iw+ih*ih)'[rotated{vindex}]")
            current_stream = f"[rotated{vindex}]"
        
        # 格式化为RGBA以支持透明度
        filter_parts.append(f"{current_stream}format=rgba[fmt{vindex}]")
        
        # 构建叠加位置
        if custom_info.x > 0 or custom_info.y > 0:
            # 使用指定的坐标位置
            overlay_x = str(int(custom_info.x))
            overlay_y = str(int(custom_info.y))
        else:
            # 默认位置：右下角留10像素边距
            overlay_x = "W-w-10"
            overlay_y = "H-h-10"
        
        # 构建叠加过滤器 - 使用计算出的实际结束时间
        # 对于视频：使用开始时间+视频时长
        # 对于图片：使用原来的结束时间
        overlay_filter = f"{last_video}[fmt{vindex}]overlay={overlay_x}:{overlay_y}:enable='between(t,{custom_info.start_time},{actual_end_time})'[v{i}_custom]"
        filter_parts.append(overlay_filter)
        
        # 处理音频流（仅对视频文件）
        audio_stream_name = None
        if is_video and video_duration:
            # 为子视频添加音频时间控制和音量调整
            # 使用adelay滤镜延迟音频到正确的开始时间，volume滤镜调整音量为30%
            delay_ms = int(custom_info.start_time * 1000)  # 转换为毫秒
            volume_level = 0.3  # 30%音量
            audio_filter = f"[{vindex}:a]volume={volume_level},adelay={delay_ms}|{delay_ms}[a{i}_custom]"
            filter_parts.append(audio_filter)
            audio_stream_name = f"[a{i}_custom]"
            
            log_info(f"添加音频流: 延迟{delay_ms}ms ({custom_info.start_time}秒)，音量调整为{int(volume_level*100)}%")
        elif is_gif:
            # GIF文件通常没有音频，但如果有的话也需要处理
            log_info(f"GIF文件通常无音频流")
        
        # 将所有过滤器部分连接起来
        filter_complex.append(";".join(filter_parts))
        
        file_type_info = "GIF" if is_gif else ("视频" if is_video else "图片")
        duration_info = f"时长:{video_duration}秒" if video_duration else "使用SRT时间"
        audio_info = "包含音频" if audio_stream_name else "无音频"
        loop_info = "循环播放" if is_gif else ""
        log_info(f"添加自定义图标: {os.path.basename(custom_info.file_path)} ({file_type_info}) 位置:({overlay_x},{overlay_y}) 开始:{custom_info.start_time}秒 结束:{actual_end_time}秒 旋转:{custom_info.angle}度 {duration_info} {audio_info} {loop_info}")
        
        return f"[v{i}_custom]", vindex + 1, audio_stream_name

    def generate_video_with_icons(self, video_path: str, match_info_list: List[FootballMatchInfo|CustomInfo], output_path: Optional[str] = None) -> Dict[str, Any]:
        """
        生成带有图标的视频
        
        Args:
            video_path: 视频文件路径
            match_info_list: 比赛信息列表
            output_path: 输出视频路径，如果为None则自动生成
        
        Returns:
            处理结果字典
        """
        if not os.path.exists(video_path):
            return {"success": False, "message": f"视频文件不存在: {video_path}"}
        
        if not match_info_list:
            return {"success": False, "message": "没有找到匹配的比赛信息"}
        
        # 如果未提供输出路径，生成一个
        if output_path is None:
            dirname = os.path.dirname(video_path)
            basename = os.path.basename(video_path)
            name, ext = os.path.splitext(basename)
            output_path = os.path.join(dirname, f"{name}_with_icons{ext}")
        
        # 获取视频信息
        video_info = self._get_video_info(video_path)
        if not video_info["success"]:
            return {"success": False, "message": f"无法获取视频信息: {video_info['message']}"}
        
        # 计算图标大小 - 视频宽度的18%
        video_width = video_info["width"]
        icon_width = int(video_width * 0.18)  # 改为18%而不是1/4
        
        # 临时文件列表，用于清理
        temp_files = []
        
        try:
            # 为每个比赛信息准备过滤器
            filter_complex = []
            input_files = [video_path]  # 视频是第一个输入
            
            # 构建过滤器串联表达式
            last_video = "[0:v]"
            vindex = 1
            audio_streams = []  # 收集所有音频流
            
            for i, info in enumerate(match_info_list):
                # 检查信息类型并分别处理
                log_info(f"处理信息 {i+1}/{len(match_info_list)}: {info}")
                if isinstance(info, CustomInfo):
                    # 处理自定义图标
                    result = self._process_custom_icon(info, last_video, vindex, i, input_files, filter_complex, temp_files)
                    if result:
                        if len(result) == 3:  # 新的返回格式包含音频流
                            last_video, vindex, audio_stream = result
                            if audio_stream:  # 如果有音频流
                                audio_streams.append(audio_stream)
                        else:  # 旧的返回格式兼容
                            last_video, vindex = result
                    continue
                
                # 处理足球比赛信息 (FootballMatchInfo)
                # 计算图标相关尺寸
                match_height = icon_width // 2  # 估算比赛图标高度
                team_height = icon_width // 2   # 估算队伍图标高度
                match_y = f"80"  # 距顶部80像素
                
                # 验证比赛图片文件是否存在
                if info.match_image and os.path.exists(info.match_image):
                    input_files.append(info.match_image)
                    # 计算X、Y坐标 (顶部中间)
                    match_x = f"(W-w)/2"
                    
                    # 使用固定宽度缩放比赛图标到视频宽度的18%
                    filter_complex.append(
                        f"[{vindex}:v]scale={icon_width}:-1[scaled{vindex}];"
                        f"[scaled{vindex}]format=rgba[fmt{vindex}];"
                        f"{last_video}[fmt{vindex}]overlay={match_x}:{match_y}"
                        f":enable='between(t,{info.start_time},{info.end_time})'[v{i}_match]"
                    )
                    last_video = f"[v{i}_match]"
                    vindex += 1
                    
                    # 有比赛图标时，队伍图标在其下方
                    team_row_y = f"{match_y}+{match_height}+60"
                else:
                    # 无比赛图标时，队伍图标直接放在顶部，位置稍低一些
                    team_row_y = f"160"
                    if info.match_image:
                        log_warning(f"比赛图片不存在: {info.match_image}")
        
                # 添加队伍1图片 - 放在左侧
                if info.team1_image and os.path.exists(info.team1_image):
                    input_files.append(info.team1_image)
                    # 计算X、Y坐标
                    team1_x = f"W*0.25-w/2"  # 屏幕宽度的1/4位置
                    
                    # 使用固定宽度缩放队伍图标到视频宽度的18%
                    filter_complex.append(
                        f"[{vindex}:v]scale={icon_width}:-1[scaled{vindex}];"
                        f"[scaled{vindex}]format=rgba[fmt{vindex}];"
                        f"{last_video}[fmt{vindex}]overlay={team1_x}:{team_row_y}"
                        f":enable='between(t,{info.start_time},{info.end_time})'[v{i}_team1]"
                    )
                    last_video = f"[v{i}_team1]"
                    vindex += 1
                    
                    # 添加队伍1名称 - 放在队伍1图标下方15px处
                    if hasattr(info, 'team1_name') and info.team1_name:
                        team1_name_image = self._create_team_name_image(info.team1_name, width=300)
                        temp_files.append(team1_name_image)
                        input_files.append(team1_name_image)
                        
                        # 计算X、Y坐标 - 与队伍图标水平居中，垂直放置在图标下方15px
                        team1_name_x = f"W*0.25-w/2"  # 与队伍图标相同的X坐标
                        team1_name_y = f"{team_row_y}+{team_height}+80"  # 队伍图标下方15px
                        
                        filter_complex.append(
                            f"[{vindex}:v]format=rgba[fmt{vindex}];"
                            f"{last_video}[fmt{vindex}]overlay={team1_name_x}:{team1_name_y}"
                            f":enable='between(t,{info.start_time},{info.end_time})'[v{i}_team1_name]"
                        )
                        last_video = f"[v{i}_team1_name]"
                        vindex += 1
                else:
                    if info.team1_image:
                        log_warning(f"队伍1图片不存在: {info.team1_image}")
            
                # 添加队伍2图片 - 放在右侧
                if info.team2_image and os.path.exists(info.team2_image):
                    input_files.append(info.team2_image)
                    # 计算X、Y坐标
                    team2_x = f"W*0.75-w/2"  # 屏幕宽度的3/4位置
                    
                    # 使用固定宽度缩放队伍图标到视频宽度的18%
                    filter_complex.append(
                        f"[{vindex}:v]scale={icon_width}:-1[scaled{vindex}];"
                        f"[scaled{vindex}]format=rgba[fmt{vindex}];"
                        f"{last_video}[fmt{vindex}]overlay={team2_x}:{team_row_y}"
                        f":enable='between(t,{info.start_time},{info.end_time})'[v{i}_team2]"
                    )
                    last_video = f"[v{i}_team2]"
                    vindex += 1
                    
                    # 添加队伍2名称 - 放在队伍2图标下方15px处
                    if hasattr(info, 'team2_name') and info.team2_name:
                        team2_name_image = self._create_team_name_image(info.team2_name, width=300)
                        temp_files.append(team2_name_image)
                        input_files.append(team2_name_image)
                        
                        # 计算X、Y坐标 - 与队伍图标水平居中，垂直放置在图标下方15px
                        team2_name_x = f"W*0.75-w/2"  # 与队伍图标相同的X坐标
                        team2_name_y = f"{team_row_y}+{team_height}+80"  # 队伍图标下方15px
                        
                        filter_complex.append(
                            f"[{vindex}:v]format=rgba[fmt{vindex}];"
                            f"{last_video}[fmt{vindex}]overlay={team2_name_x}:{team2_name_y}"
                            f":enable='between(t,{info.start_time},{info.end_time})'[v{i}_team2_name]"
                        )
                        last_video = f"[v{i}_team2_name]"
                        vindex += 1
                else:
                    if info.team2_image:
                        log_warning(f"队伍2图片不存在: {info.team2_image}")
            
                # 添加比分图片 - 放在与队伍图标水平居中的位置
                score_image = self._create_score_image(info.score1, info.score2, width=400, height=120)
                temp_files.append(score_image)
                input_files.append(score_image)
                
                # 计算X、Y坐标 - 保持水平居中
                score_x = f"(W-w)/2"  # 水平居中
                score_y = f"{team_row_y}"  # 与调整后的队伍图标在同一高度
                
                # 添加比分图片，不需要缩放
                filter_complex.append(
                    f"[{vindex}:v]format=rgba[fmt{vindex}];"
                    f"{last_video}[fmt{vindex}]overlay={score_x}:{score_y}"
                    f":enable='between(t,{info.start_time},{info.end_time})'[v{i}_score]"
                )
                last_video = f"[v{i}_score]"
                vindex += 1
    
            # 如果没有有效的叠加效果，直接复制视频
            if last_video == "[0:v]":
                return {"success": False, "message": "没有有效的图标可以叠加到视频上"}
            
            # 处理音频混合
            final_audio_output = "0:a?"  # 默认使用原始音频
            if audio_streams:
                log_info(f"检测到 {len(audio_streams)} 个音频流，进行混合")

                if len(audio_streams) == 1:
                    audio_mix_filter = f"[main_audio]{audio_streams[0]}amix=inputs=2:duration=longest:dropout_transition=0:normalize=0[mixed_audio]"
                    filter_complex.append(audio_mix_filter)
                    final_audio_output = "[mixed_audio]"
                else:
                    # 混合所有子视频音频
                    sub_audio_mix = "".join(audio_streams) + f"amix=inputs={len(audio_streams)}:duration=longest:dropout_transition=0:normalize=0[sub_mixed]"
                    filter_complex.append(sub_audio_mix)

                    # 再与主音频混合
                    final_mix_filter = "[main_audio][sub_mixed]amix=inputs=2:duration=longest:dropout_transition=0:normalize=0[mixed_audio]"
                    filter_complex.append(final_mix_filter)
                    final_audio_output = "[mixed_audio]"
            else:
                # 没有子视频音频时，直接用主音频
                filter_complex.append("[0:a]anull[mixed_audio]")
                final_audio_output = "[mixed_audio]"

            
            # 构建命令
            cmd = ["ffmpeg", "-y"]
            
            # 添加所有输入文件
            for input_file in input_files:
                cmd.extend(["-i", input_file])
            
            # 添加复杂过滤器
            filter_str = ";".join(filter_complex)
            cmd.extend(["-filter_complex", filter_str])
            
            # 设置输出选项
            cmd.extend([
                "-map", last_video,  # 使用最后一个视频流
                "-map", final_audio_output,  # 使用混合后的音频或原始音频
                "-c:v", "libx264",
                "-preset", "medium", 
                "-crf", "23",
                "-c:a", "aac",  # 使用AAC编码音频以确保兼容性
                "-b:a", "128k",  # 设置音频比特率
                output_path
            ])
            
            # 执行命令
            log_info(f"开始添加足球图标到视频: {os.path.basename(video_path)}")
            log_info(f"FFmpeg命令: {' '.join(cmd)}")
            
            process = subprocess.Popen(
                cmd, 
                stdout=subprocess.PIPE, 
                stderr=subprocess.PIPE,
                startupinfo=self.startupinfo,
                universal_newlines=True
            )
            
            _, stderr = process.communicate()
            
            # 检查处理结果
            if process.returncode != 0:
                log_error(f"添加图标失败: {stderr}")
                return {"success": False, "message": "添加图标失败", "error": stderr}
            
            # 验证输出文件
            if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
                log_info(f"图标添加成功: {output_path}")
                return {
                    "success": True,
                    "message": "图标添加成功",
                    "output_path": output_path
                }
            else:
                log_error("输出文件生成失败或为空")
                return {"success": False, "message": "输出文件生成失败或为空"}
            
        except Exception as e:
            log_error(f"处理图标视频时发生错误: {str(e)}")
            import traceback
            log_error(traceback.format_exc())
            return {"success": False, "message": f"处理错误: {str(e)}"}
        
        finally:
            # 清理临时文件
            for temp_file in temp_files:
                try:
                    if os.path.exists(temp_file):
                        os.remove(temp_file)
                except Exception as e:
                    log_warning(f"删除临时文件失败: {e}")

    def parse_and_generate(self, video_paths: List[str], subtitle_path: str) -> Dict[str, Any]:
        """
        解析字幕并生成带有图标的视频
        
        Args:
            video_paths: 视频文件路径列表
            subtitle_path: 字幕文件路径
            
        Returns:
            处理结果字典
        """
        try:
            # 验证输入参数
            if not os.path.exists(subtitle_path):
                raise FileNotFoundError(f"字幕文件不存在: {subtitle_path}")
                
            if not video_paths or not isinstance(video_paths, list):
                raise ValueError("视频路径列表不能为空且必须是列表类型")
            
            # 解析字幕文件，提取比赛信息
            match_info_list = self._parse_srt_file(subtitle_path)
            log_info(f"解析到 {len(match_info_list)} 条待处理信息")
            log_info(match_info_list)
            
            if not match_info_list:
                raise ValueError("在字幕文件中没有找到有效的待处理信息")
            
            # 处理每个视频文件
            results = []
            
            for video_path in video_paths:
                if not os.path.exists(video_path):
                    log_warning(f"视频文件不存在: {video_path}")
                    results.append({
                        "video_path": video_path,
                        "output_path": "",
                        "success": False,
                        "message": "视频文件不存在"
                    })
                    continue
                    
                log_info(f"开始处理视频: {os.path.basename(video_path)}")
                
                # 为每个视频生成带有图标的版本
                result = self.generate_video_with_icons(
                    video_path=video_path,
                    match_info_list=match_info_list
                )
                
                results.append({
                    "video_path": video_path,
                    "output_path": result.get("output_path", ""),
                    "success": result.get("success", False),
                    "message": result.get("message", "")
                })
            
            # 统计成功和失败的数量
            success_count = sum(1 for r in results if r.get("success", False))
            
            return results, success_count
            
        except Exception as e:
            raise Exception(f"解析和生成视频时发生错误: {str(e)}") from e

